<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>The source code</title>
  <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  <style type="text/css">
    .highlight { display: block; background-color: #ddd; }
  </style>
  <script type="text/javascript">
    function highlight() {
      document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
    }
  </script>
</head>
<body onload="prettyPrint(); highlight();">
  <pre class="prettyprint lang-js"><span id='global-property-'>/**
</span> * combination of menu and button ,similar to native select
 * @ignore
 * @author yiminghe@gmail.com
 */
KISSY.add(&quot;menubutton/control&quot;, function (S, Node, Button, MenuButtonRender, Menu, undefined) {

    var KeyCode = Node.KeyCode;
<span id='KISSY-MenuButton'>    /**
</span>     * A menu button component, consist of a button and a drop down popup menu.
     * xclass: 'menu-button'.
     * @class KISSY.MenuButton
     * @extends KISSY.Button
     */
    return Button.extend({

        isMenuButton: 1,

        _onSetCollapsed: function (v) {
            var self = this,
                menu = self.get(&quot;menu&quot;);
            if (v) {
                menu.hide();
            } else {
                var el = self.$el;
                if (!menu.get(&quot;visible&quot;)) {
                    // same as submenu
                    // in case menu is changed after menubutton is rendered
                    var align = {
                        node: el,
                        points: [&quot;bl&quot;, &quot;tl&quot;],
                        overflow: {
                            adjustX: 1,
                            adjustY: 1
                        }
                    };
                    S.mix(menu.get('align'), align, false);
                    if (self.get(&quot;matchElWidth&quot;)) {
                        menu.render();
                        var menuEl = menu.get('el');
                        var borderWidth =
                            (parseInt(menuEl.css('borderLeftWidth')) || 0) +
                                (parseInt(menuEl.css('borderRightWidth')) || 0);
                        menu.set(&quot;width&quot;, menu.get(&quot;align&quot;).node[0].offsetWidth - borderWidth);
                    }
                    menu.show();
                    el.attr(&quot;aria-haspopup&quot;, menu.get('el').attr(&quot;id&quot;));
                }
            }
        },

        bindUI: function () {
            var self = this;
            self.on('afterHighlightedItemChange',
                onMenuAfterHighlightedItemChange, self);
            self.on('click', onMenuItemClick, self);
        },

<span id='KISSY-MenuButton-method-handleKeyDownInternal'>        /**
</span>         * Handle keydown/up event.
         * If drop down menu is visible then handle event to menu.
         * Returns true if the event was handled, falsy otherwise.
         * Protected, should only be overridden by subclasses.
         * @param {KISSY.Event.DomEvent.Object} e key event to handle.
         * @return {Boolean|undefined} True Whether the key event was handled.
         * @protected
         */
        handleKeyDownInternal: function (e) {
            var self = this,
                keyCode = e.keyCode,
                type = String(e.type),
                menu = self.get(&quot;menu&quot;);

            // space 只在 keyup 时处理
            if (keyCode == KeyCode.SPACE) {
                // Prevent page scrolling in Chrome.
                e.preventDefault();
                if (type != &quot;keyup&quot;) {
                    return undefined;
                }
            } else if (type != &quot;keydown&quot;) {
                return undefined;
            }
            //转发给 menu 处理
            if (menu.get('rendered') &amp;&amp; menu.get(&quot;visible&quot;)) {
                var handledByMenu = menu.handleKeyDownInternal(e);
                // esc
                if (keyCode == KeyCode.ESC) {
                    self.set(&quot;collapsed&quot;, true);
                    return true;
                }
                return handledByMenu;
            }

            // Menu is closed, and the user hit the down/up/space key; open menu.
            if (keyCode == KeyCode.SPACE ||
                keyCode == KeyCode.DOWN ||
                keyCode == KeyCode.UP) {
                self.set(&quot;collapsed&quot;, false);
                return true;
            }
            return undefined;
        },

<span id='KISSY-MenuButton-method-handleClickInternal'>        /**
</span>         * Perform default action for menubutton.
         * Toggle the drop down menu to show or hide.
         * Protected, should only be overridden by subclasses.
         * @protected
         *
         */
        handleClickInternal: function () {
            var self = this;
            self.set(&quot;collapsed&quot;, !self.get(&quot;collapsed&quot;));
        },

<span id='KISSY-MenuButton-method-handleBlurInternal'>        /**
</span>         * Handles blur event.
         * When it loses keyboard focus, close the drop dow menu.
         * @param {KISSY.Event.DomEvent.Object} e Blur event.
         * Protected, should only be overridden by subclasses.
         * @protected
         *
         */
        handleBlurInternal: function (e) {
            var self = this;
            self.callSuper(e);
            // such as : click the document
            self.set(&quot;collapsed&quot;, true);
        },


<span id='KISSY-MenuButton-method-addItem'>        /**
</span>         * Adds a new menu item at the end of the menu.
         * @param {KISSY.Menu.Item} item Menu item to add to the menu.
         * @param {Number} index position to insert
         */
        addItem: function (item, index) {
            var menu = this.get(&quot;menu&quot;);
            menu.addChild(item, index);
        },

<span id='KISSY-MenuButton-method-removeItem'>        /**
</span>         * Remove a existing menu item from drop down menu.
         * @param c {KISSY.Menu.Item} Existing menu item.
         * @param [destroy=true] {Boolean} Whether destroy removed menu item.
         */
        removeItem: function (c, destroy) {
            var menu = this.get(&quot;menu&quot;);
            menu.removeChild(c, destroy);
        },

<span id='KISSY-MenuButton-method-removeItems'>        /**
</span>         * Remove all menu items from drop down menu.
         * @param [destroy] {Boolean} Whether destroy removed menu items.
         */
        removeItems: function (destroy) {
            var menu = this.get(&quot;menu&quot;);
            if (menu) {
                if (menu.removeChildren) {
                    menu.removeChildren(destroy);
                } else if (menu.children) {
                    menu.children = [];
                }
            }
        },

<span id='KISSY-MenuButton-method-getItemAt'>        /**
</span>         * Returns the child menu item of drop down menu at the given index, or null if the index is out of bounds.
         * @param {Number} index 0-based index.
         */
        getItemAt: function (index) {
            var menu = self.get(&quot;menu&quot;);
            return menu.get('rendered') &amp;&amp; menu.getChildAt(index);
        },

        // 禁用时关闭已显示菜单
        _onSetDisabled: function (v) {
            var self = this;
            !v &amp;&amp; self.set(&quot;collapsed&quot;, true);
        },

        destructor: function () {
            this.get('menu').destroy();
        }

    }, {
        ATTRS: {

<span id='KISSY-MenuButton-cfg-matchElWidth'>            /**
</span>             * Whether drop down menu is same width with button.
             * Defaults to: true.
             * @cfg {Boolean} matchElWidth
             */
<span id='global-property-matchElWidth'>            /**
</span>             * @ignore
             */
            matchElWidth: {
                value: true
            },

<span id='KISSY-MenuButton-cfg-collapseOnClick'>            /**
</span>             * Whether hide drop down menu when click drop down menu item.
             * eg: u do not want to set true when menu has checked menuitem.
             * Defaults to: false
             * @cfg {Boolean} collapseOnClick
             */
<span id='global-property-collapseOnClick'>            /**
</span>             * @ignore
             */
            collapseOnClick: {
                value: false
            },
<span id='KISSY-MenuButton-cfg-menu'>            /**
</span>             * Drop down menu associated with this menubutton.
             * @cfg {KISSY.Menu|Object} menu
             */

<span id='KISSY-MenuButton-property-menu'>            /**
</span>             * Drop down menu associated with this menubutton.
             * @property {KISSY.Menu} menu
             */


<span id='global-property-menu'>            /**
</span>             * @ignore
             */
            menu: {
                value: {},
                getter: function (v) {
                    if (!v.isControl) {
                        v.xclass = v.xclass || 'popupmenu';
                        v = this.createComponent(v);
                        this.setInternal('menu', v);
                    }
                    return v;
                },
                setter: function (m) {
                    if (m.isControl) {
                        m.setInternal('parent', this);
                    }
                }
            },

<span id='KISSY-MenuButton-property-collapsed'>            /**
</span>             * Whether drop menu is shown.
             * @property {Boolean} collapsed
             */
<span id='global-property-collapsed'>            /**
</span>             * @ignore
             */
            collapsed: {
                value: false,
                view: 1
            },

            xrender: {
                value: MenuButtonRender
            }
        },
        xclass: 'menu-button'
    });

    function onMenuItemClick(e) {
        if (e.target.isMenuItem &amp;&amp; this.get('collapseOnClick')) {
            this.set(&quot;collapsed&quot;, true);
        }
    }

    function onMenuAfterHighlightedItemChange(e) {
        if (e.target.isMenu) {
            var el = this.el,
                menuItem = e.newVal;
            el.setAttribute(&quot;aria-activedescendant&quot;, menuItem &amp;&amp; menuItem.el.id || '');
        }
    }
}, {
    requires: [ &quot;node&quot;, &quot;button&quot;, &quot;./render&quot;, &quot;menu&quot;]
});</pre>
</body>
</html>
